#pragma once
/*****************************************实现数据库版本的题目交互***************************** */
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cassert>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <mysql/mysql.h>

#include "../comm/log.hpp"
#include "../comm/util.hpp"

namespace ns_model_mysql
{
    using namespace ns_log;
    using namespace ns_util;

    struct Question
    {
        std::string number; // 题目标题, 唯一性
        std::string title;  // 题目标题
        std::string star;   // 题目难度
        int cpulimit;       // 题目时间限制
        int memlimit;       // 题目空间限制
        std::string desc;   // 题目描述
        std::string header; // 题目预设置代码
        std::string tail;   // 题目测试代码部分
    };

    // 该类实现题库的交互
    class Model
    {
    public:
        Model()
        {
        }
        ~Model()
        {
        }

    private:
        const std::string databasename = "oj";
        const std::string tablename = "oj_questions";
        const std::string user = "oj_client";
        const std::string host = "127.0.0.1";
        const std::string passward = "123456";
        const int port = 3306;
        /***********
         * 功能：实现对数据库的访问，将题目信息返回
         * query：执行的sql语句
         * out：输出型参数，将结果带回
         *******/
        bool QueryMysql(const std::string &query, std::vector<Question> *out)
        {
            // 1、链接数据库。这里就直接写死了

            // 1.2构建Mysql权柄
            MYSQL *my = mysql_init(nullptr);

            // 1.3建立链接
            if (nullptr == mysql_real_connect(my, host.c_str(), user.c_str(), passward.c_str(), databasename.c_str(), port, nullptr, 0))
            {
                LOG(Fatal, "数据库连接失败");
                return false;
            }
            LOG(Info, "数据库连接成功");

            mysql_set_character_set(my, "utf8mb4"); // 设置连接的时候的字符编码格式
            // 执行sql语句
            if (0 != mysql_query(my, query.c_str()))
            {
                LOG(Warning, "执行sql语句失败: %s", query.c_str());
                return false;
            }

            // 执行成功，提取语句
            MYSQL_RES *res = mysql_store_result(my);
            if(nullptr == res)
            {
                LOG(Fatal, "未能获取语句结果");
                return false;
            }

            int rows = mysql_num_rows(res);

            Question q;
            for (int i = 0; i < rows; ++i)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                q.number = row[0];
                q.title = row[1];
                q.star = row[2];
                q.desc = row[3];
                q.header = row[4];
                q.tail = row[5];
                q.cpulimit = atoi(row[6]);
                q.memlimit = atoi(row[7]);

                out->push_back(q);
            }
            // 释放空间
            mysql_free_result(res);
            // 关闭权柄
            mysql_close(my);
            return true;
        }

    public:
        /*********************
         * 功能：将所有的题目获取出来
         *******************/
        bool GetAllQuestions(std::vector<Question> *out)
        {
            std::string sqlquery = "select * from ";
            sqlquery += tablename;
            if(QueryMysql(sqlquery, out))
            {
                std::sort(out->begin(), out->end(), [](const Question& q1, const Question& q2){
                    return std::stoi(q1.number) < std::stoi(q2.number);
                });
                return true;
            }
            return false;
        }
        /*********************
         * 功能：将传入的单个的题目获取出来
         *******************/
        bool GetOneQuestions(const std::string &number, Question *out)
        {
            std::string sqlquery = "select * from ";
            sqlquery += tablename;
            sqlquery += " where id=" + number; //表结构没有建好，有差异命名
            std::vector<Question> q;
            if(QueryMysql(sqlquery, &q))
            {
                if(1 == q.size())
                {
                    *out = q[0];
                    return true;
                }
            }
            return false;
        }
        // TODO 对题库的增删改查 —> 我们就不做了
    };

} // namespace ns_model
